| Scope | Activation | Duplicates | Global prop. | |
|---|---|---|---|---|
| const | Block | decl.(TDZ) | X | X |
| let | Block | decl.(TDZ) | X | X |
| function | Block* | start | O | O |
| class | Block | decl.(TDZ) | X | X |
| import | Module | same as export | X | X |
| var | Function | start, partially | O | O |
strict mode가 아닐 때는 Function 범위아래에서 더 자세하게 살펴보자
let, const에 해당한다.{
console.log(x); // ???
const x;
}
선언된 범위(Scope) 내에서 선언까지 도달하기 전 사용이 불가능하기 떄문에 에러를 뱉는다.
범위 내에서 선언에 도달하기 까지의 구간을 TDZ(일시적 사용 불가 구간)라고 한다.
ReferenceError가 발생한다.undefined가 된다.다음 예제는 TDZ가 실제로 일시적으로 존재함을 알려준다.
if (true) {
// myVar이 선언되어있는 스코프에 진입
const func = () => {
console.log(myVar) // 함수 실행시점에 myVar이 TDZ를 벗어났으면 실행
}
// 아래 myVar 선언되기 전에 사용하려는 경우 ReferenceError가 뜰 것이다.
let myVar = 3 // TDZ가 끝났다.
func() // myVar의 TDZ가 끝났기 때문에 에러가 아니다.
}
함수가 있는 Scope에 접근할 때 함수 선언은 Scope내 어디에 있든 항상 실행된다. 즉, Scope내 어디서든 선언만 되어있다면 언제든 사용할 수 있다.
하지만, 다음의 경우는 유의해야한다.
const, let을 이용하여 함수를 선언/할당한 경우funcDecl() // funcDecl이 선언된 Scope니까 함수의 실행은 가능하다
// 그러나 함수의 내용을 보면 MY_STR const를 사용하는데, MY_STR는 아직 선언되지 않았으므로 에러가 발생한다.
const MY_STR = "abc"
function funcDecl() {
assert.throws(
() => MY_STR, // 함수 선언될 때 없음
ReferenceError
)
}
Class는 선언한 이후에 사용 가능해야한다.
class의 상속 기능인 extends가 expression이기 때문이다.
extends시에는 계산이 이뤄지기 때문에 다음과 같은 코드가 가능하다.
const c = new Cat() // 이럼 안된다.
const identity = x => x
class Cat extends identity(Animal) {}
다시말하자면, class의 선언은 extends를 통해 어떤 값을 받아 처리하는 expression이고, 때문에 expression에 대한 statement의 처리는 실행하는 시점에 이뤄진다.
ℹ️ expression은 값을 나타내고, statement는 행위의 선언이다.
아까 표에서 var는 Javascript실행시 부분적으로 사용가능하다고 되어있었다.
var x = 123
var의 선언은 두 부분으로 나뉜다.
var x: var로 선언된 변수를 담고있는 가장 안쪽의 함수 Scopex = 123: 값은 대입한 시점 이후부터 사용가능function f() {
assert.equal(x, undefined) // 가장 안쪽의 함수 Scope에서 선언. undefined로 초기화됨
if (true) {
var x = 123 // 이제 123 값을 갖게됨 + Block안에서 선언했지만 위 설명대로..
assert.equal(x, 123)
}
assert.equal(x, 123) // 여기선 123
}